package utils

import (
	"context"
	"errors"
	"fmt"
	"nexus/internal/config"
	"time"

	"github.com/zeromicro/go-zero/core/logc"
	"github.com/zeromicro/go-zero/core/service"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

type Logger struct {
	SlowThreshold time.Duration
	Level         logger.LogLevel
	c             config.Config
}

func NewLogger(c config.Config) *Logger {
	// 默认日志级别
	logLevel := logger.Warn

	// 根据配置设置日志级别
	switch c.Logger.Level {
	case "silent":
		logLevel = logger.Silent
	case "error":
		logLevel = logger.Error
	case "info":
		logLevel = logger.Info
	}

	return &Logger{
		SlowThreshold: time.Duration(c.Logger.SlowThreshold) * time.Millisecond, // 一般超过200毫秒就算慢查所以不使用配置进行更改
		Level:         logLevel,
		c:             c,
	}
}

var _ logger.Interface = (*Logger)(nil)

func (l *Logger) LogMode(level logger.LogLevel) logger.Interface {
	newLogger := *l
	newLogger.Level = level
	return &newLogger
}

func (l *Logger) Info(ctx context.Context, msg string, data ...interface{}) {
	if l.Level >= logger.Info {
		logc.Infof(ctx, "[GORM] "+msg, data...)
	}
}

func (l *Logger) Warn(ctx context.Context, msg string, data ...interface{}) {
	if l.Level >= logger.Warn {
		logc.Errorf(ctx, "[GORM] "+msg, data...)
	}
}

func (l *Logger) Error(ctx context.Context, msg string, data ...interface{}) {
	if l.Level >= logger.Error {
		logc.Errorf(ctx, "[GORM] "+msg, data...)
	}
}

func (l *Logger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
	if l.Level <= logger.Silent {
		return
	}

	elapsed := time.Since(begin)
	sql, rows := fc()

	// 通用日志字段
	logFields := []logc.LogField{
		logc.Field("sql", sql),
		logc.Field("time", fmt.Sprintf("%.3fms", float64(elapsed.Nanoseconds())/1e6)),
		logc.Field("rows", rows), // 添加调用者信息
	}

	// 错误处理
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			if l.Level >= logger.Warn {
				logc.Infow(ctx, "[GORM] Record not found", logFields...)
			}
		} else {
			logFields = append(logFields, logc.Field("error", err.Error()))
			if l.Level >= logger.Error {
				logc.Errorw(ctx, "[GORM] Database error", logFields...)
			}
		}
		return
	}

	// 慢查询日志
	if l.SlowThreshold != 0 && elapsed > l.SlowThreshold {
		if l.Level >= logger.Warn {
			logFields = append(logFields, logc.Field("slow_threshold", l.SlowThreshold.String()))
			logc.Sloww(ctx, "[GORM] Slow SQL", logFields...)
		}
		return
	}

	// 开发模式下的全量日志
	if l.c.Mode != service.ProMode && l.Level >= logger.Info {
		logc.Infow(ctx, "[GORM] SQL Query", logFields...)
	}
}
